package com.stable.actor.network;

import com.stable.actor.core.ActorSystem;


import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 完整的TCP服务器 - 处理Actor远程消息
 */
public class TcpServer {
    private final int port;
    private final String actorPath;
    private final ActorSystem actorSystem;
    private ServerSocket serverSocket;
    private ExecutorService executor;
    private volatile boolean running = false;

    public TcpServer(int port, String actorPath, ActorSystem actorSystem) {
        this.port = port;
        this.actorPath = actorPath;
        this.actorSystem = actorSystem;
    }

    public void start() {
        try {
            serverSocket = new ServerSocket(port);
            executor = Executors.newFixedThreadPool(10);
            running = true;

            System.out.println("🌐 TCP服务器启动在端口: " + port + ", 路径: " + actorPath);

            // 接受连接
            new Thread(this::acceptConnections, "TcpServer-" + port).start();

        } catch (IOException e) {
            System.err.println("❌ 启动TCP服务器失败，端口 " + port + ": " + e.getMessage());
        }
    }

    private void acceptConnections() {
        while (running) {
            try {
                Socket clientSocket = serverSocket.accept();
                System.out.println("🔗 接收到客户端连接: " + clientSocket.getInetAddress() + ":" + clientSocket.getPort());

                // 处理客户端连接
                executor.submit(() -> handleClient(clientSocket));

            } catch (IOException e) {
                if (running) {
                    System.err.println("❌ 接受连接失败: " + e.getMessage());
                }
            }
        }
    }

    private void handleClient(Socket clientSocket) {
        try (InputStream input = clientSocket.getInputStream();
             OutputStream output = clientSocket.getOutputStream()) {

            System.out.println("📨 处理客户端消息，端口: " + port);

            // 读取消息长度头 (4字节)
            byte[] header = new byte[4];
            int bytesRead = readFully(input, header);
            if (bytesRead != 4) {
                System.err.println("❌ 读取消息头失败");
                return;
            }

            int messageLength = bytesToInt(header);
            System.out.println("📏 消息长度: " + messageLength);

            // 读取消息体
            byte[] messageData = new byte[messageLength];
            bytesRead = readFully(input, messageData);
            if (bytesRead != messageLength) {
                System.err.println("❌ 读取消息体失败，期望: " + messageLength + ", 实际: " + bytesRead);
                return;
            }

            // 解码消息
            ProtocolMessage message = MessageCodec.decode(messageData);
            System.out.println("📨 收到消息 - 发送者: " + message.getSenderPath() + ", 目标: " + message.getTargetPath());

            // 检查发送者路径
            if (message.getSenderPath() == null || "no-sender".equals(message.getSenderPath())) {
                System.out.println("⚠️ 消息没有有效发送者，无法回复");
                return;
            }

            // 模拟处理消息并生成响应
            String responseContent = "服务 " + actorPath + " 处理成功: " + message.getPayload();
            ServiceResponse response = new ServiceResponse(
                    getServiceTypeFromPath(actorPath),
                    true,
                    responseContent
            );

            // 编码响应
            ProtocolMessage responseMessage = new ProtocolMessage();
            responseMessage.setSenderPath(actorPath);
            responseMessage.setTargetPath(message.getSenderPath());
            responseMessage.setPayload(response);
            responseMessage.setMessageId("resp-" + System.currentTimeMillis());
            responseMessage.setTimestamp(System.currentTimeMillis());

            byte[] responseData = MessageCodec.encode(responseMessage);
            byte[] responseHeader = intToBytes(responseData.length);

            // 发送响应
            output.write(responseHeader);
            output.write(responseData);
            output.flush();

            System.out.println("✅ 响应发送完成，端口: " + port);

            // 关键修改：使用静态路由方法将响应路由回原始发送者
            System.out.println("🔄 尝试路由响应到原始发送者: " + message.getSenderPath());
            ActorSystem.routeMessage(message.getSenderPath(), response);

        } catch (Exception e) {
            System.err.println("❌ 处理客户端消息失败，端口 " + port + ": " + e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                // 忽略关闭异常
            }
        }
    }

    private int readFully(InputStream input, byte[] buffer) throws IOException {
        int totalRead = 0;
        while (totalRead < buffer.length) {
            int read = input.read(buffer, totalRead, buffer.length - totalRead);
            if (read == -1) {
                // 连接正常关闭，不是错误
                if (totalRead == 0) {
                    throw new EOFException("连接中断，已读取 " + totalRead + " 字节，期望 " + buffer.length);
                } else {
                    // 部分读取，可能是协议错误
                    throw new EOFException("连接中断，已读取 " + totalRead + " 字节，期望 " + buffer.length);
                }
            }
            totalRead += read;
        }
        return totalRead;
    }

    private byte[] intToBytes(int value) {
        return new byte[] {
                (byte) (value >>> 24),
                (byte) (value >>> 16),
                (byte) (value >>> 8),
                (byte) value
        };
    }

    private int bytesToInt(byte[] bytes) {
        return ((bytes[0] & 0xFF) << 24) |
                ((bytes[1] & 0xFF) << 16) |
                ((bytes[2] & 0xFF) << 8) |
                (bytes[3] & 0xFF);
    }

    private String getServiceTypeFromPath(String path) {
        if (path.contains("payment")) return "payment";
        if (path.contains("inventory")) return "inventory";
        if (path.contains("notification")) return "notification";
        return "unknown";
    }

    public void stop() {
        running = false;
        try {
            if (serverSocket != null) {
                serverSocket.close();
            }
            if (executor != null) {
                executor.shutdown();
            }
            System.out.println("🛑 TCP服务器停止，端口: " + port);
        } catch (IOException e) {
            System.err.println("❌ 停止TCP服务器失败: " + e.getMessage());
        }
    }
}
